The aim of this particle tutorial, is to build a simple particle fountain, controlled by mouse, from the ground up.
At every interim step, it is the intention to have a working program so that you can see what the results are of the piecemeal changes. You can either cut and paste the code in this document to the Basic-256 code window (although indentation gets lost.) or use the hyperlinks to the example programs.
What is a particle system?
A particle system in computer graphics is a technique used to simulate complex visual effects that are difficult to render with conventional methods. It involves creating a large number of small, simple objects (particles) and animating them to create the illusion of more complex, "fuzzy" phenomena like explosions, fire, smoke, sparks, waterfalls, clouds, fog, petals, grass, bubbles, and so on.
In this tutorial however, we will keep things a LOT simpler. In our particle system, each particle will have its own series of properties related to its behavior (for example, position, velocity, age, etc.). We will start our particle system from a blank slate
Basic-256 Boilerplate
For building up our particle system program, we will use the following scaffolding
Fastgraphics # write to video buffer.
size_x=800
size_y=800 # good practice to put every constant in a variable.
graphsize size_x,size_y # feel free to change the size of your canvas
color black
rect 0,0,size_x-1,size_y-1 # start out with a nice black screen.
refresh # dump the video buffer to screen
#Voila! This gives you a nice canvas to draw on.
Running this program gives us a nice black background. Not really exciting yet
Download CodeFirst, we need to define the specifics of our particle system. The particle system itself is stored into a multidimensional array, a grid if you like. The first element of the array denotes the number of particles in our system. (the number of lines on the grid) Here we will limit us to 300. (Feel free to adapt to the power of your system) The second denotes the number of properties each particle has. (the number of columns on the grid)
For an initial, minimal particle system, we will need x-position, y-position, x-velocity, y-velocity. This makes 4 properties in all.
We will set up the particle system to start from the centre, so x-position and y-position will be 400 (half of the 800x800 graphsize)
For the x- and y-velocities, we will take a very small number, here between -0.25 and 0.25.
Partnum=300
Dim Particle (Partnum,4) #particle system with 300 particles with 4 properties
for p = 0 to Partnum-1
Particle[p,0] = size_x/2
Particle[p,1]= size_y/2
Particle[p,2]= (rand-0.5)/2 # velocity from -0.25 to 0.25
Particle[p,3]= (rand-0.5)/2 #velocity from -0.25 to 0.25
next p
If we now dump our particles to the screen, we would just see a dot in the middle of a black screen as all particles are bunched up together. A particle system however is a dynamic system, so we will have to update it continually and reshow it.
We update our particle system by adding the velocities to the respective positions, we show the new screen and we clear it again. Finally we loop it with a simple goto-loop
Loop:
for p = 0 to Partnum-1 #write all the particles to the buffer and update them
color white
plot (Particle[p,0],Particle[p,1])
Particle[p,0]= Particle[p,0]+Particle[p,2]
Particle[p,1]= Particle[p,1]+Particle[p,3]
next p
Refresh #all particles shown updated on the screen
color black
rect 0,0, size_x-1,size_y-1 #initialize the screen to black again
goto Loop # do it all again
Now, if we run this program, we already get a nice star-burst effect, but it quickly fizzles out as most points move beyond the screen borders. (Feel free to change the number of particles and their velocities. Experimenting is fun!)
DownloadThere are 2 easy ways to prevent this fizzling out, to keep the particle system constrained within the borders of the graphics area.
-/ We bounce the particles of the screen borders by reversing the velocity direction for the impacted screen border (either x-velocity or y-velocity). This however turn chaotic very quickly
-/ Once it moves out of view, we reinitialize the particle to the centre of our screen again
First Option
In the loop where we update the x- and y-positions, we check if the particle has moved off the screen. If so we reverse the direction:
for p = 0 to Partnum-1 #write the particles to the buffer and update them
color white
plot (Particle[p,0],Particle[p,1])
Particle[p,0]= Particle[p,0]+Particle[p,2]
if Particle[p,0] < 0 or Particle [p,0]>size_x then Particle[p,2]= -Particle[p,2]
Particle[p,1]= Particle[p,1]+Particle[p,3]
if Particle[p,1] < 0 or Particle [p,1]>size_y then Particle[p,3]= -Particle[p,3]
next p
If we now run the program with this updated loop, we quickly find us in a chaotic situation with particles bouncing all over the place.
DownloadTo stop the chaotic motion after the Particles start to bounce off the screen edges, we can do the following:
-/ add a bit of gravity (by slightly increasing the y-speed)
-/ dampen the bounce (by multiply y-speed with eg 0.7-0.9 when the particle 'bounces').
For the gravity, we add a gravity parameter next to the array definition and set it to eg 0.001. (This is because on my system, I get about 500 full iteration loops per second. As we add gravity at every loop, the gravity influencssystem very quickly. Again experiment with this.).
For the dampening and in order to get some variation in the bounce, we dampen the bounce with a factor between 0.7 and 0.9.
This leads us to the following code changes
grav=0.001 # gravity increase
for p = 0 to Partnum-1 #write the particles to the buffer and update them
color white
plot (Particle[p,0],Particle[p,1])
Particle[p,0]= Particle[p,0]+Particle[p,2]
if Particle[p,0] < 0 or Particle [p,0]>size_x then Particle[p,2]=-Particle[p,2]*(0.7+rand/5)
Particle[p,1]= Particle[p,1]+Particle[p,3]
if Particle[p,1] < 0 then Particle[p,3]= - Particle[p,3] # bounce off ceiling
if Particle [p,1]>size_y then Particle[p,3]= - Particle[p,3]*(0.7+rand/5)bounce + dampen
Particle[p,3]= Particle[p,3]+grav # artificial gravity
next p
Download
In the second option to improve the simple starburst (disregarding the gravity addition), we have to prevent our particles from escaping the screen. We do this by reinitialising the particle to the centre of the screen if the particle has moved off the screen.
for p = 0 to Partnum-1 #write the particles to the buffer and update them
color white
plot (Particle[p,0],Particle[p,1])
Particle[p,0]= Particle[p,0]+Particle[p,2]
Particle[p,1]= Particle[p,1]+Particle[p,3]
if Particle[p,0]< 0 or Particle [p,0]>size_x or Particle[p,1]< 0 or Particle [p,1]> size_y then
Particle[p,0]= size_x/2
Particle[p,1]= size_y/2
endif
next p
If we now run the program with this updated loop, we see a never ending stream of particles being emitted from the centre.
DownloadHmmmm. In option one the particles come to rest and remain there indefinitely while in option two, the particles are being respawned. How can we combine this?
Well, we do this by giving each particle a random lifetime (random between certain limits) and decreasing the lifetime at every loop.
When the lifetime hits zero, we reinitialize the particle.
This lifetime will be a 5th property of the particle, so we have to change the size and the initialization of the array:
Dim Particle (300,5) #define a 300 particle system with 5 properties
and
for p = 0 to Partnum-1
Particle[p,0] = size_x/2
Particle[p,1]= size_y/2 # as we have gravity, we can moe this higher (eg size_y/6)
Particle[p,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[p,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[p,4]= rand *1020 # play with this setting until you get a nice bouncy effect
next p
Now that we have a life property (Particle[p,4]), we also need to decrease it so we check for viability and if dead (ie life < 0), we reinitialize the particle:
for p = 0 to Partnum-1 #write the particles to the buffer and update them
color white
plot (Particle[p,0],Particle[p,1])
Particle[p,0]= Particle[p,0]+Particle[p,2]
if Particle[p,0]<0 or Particle [p,0]>size_x then Particle[p,2]= -Particle[p,2]* (0.7+rand/5)
Particle[p,1]= Particle[p,1]+Particle[p,3]
if Particle[p,1] < 0 then Particle[p,3]= - Particle[p,3] # bounce off ceiling
if Particle [p,1]>size_y then Particle[p,3]= - Particle[p,3]* (0.5+rand/5)#bounce + dampen
Particle[p,3]= Particle[p,3]+grav # artificial gravity
Particle[p,4]= Particle[p,4]-1
if Particle[p,4]<0 then
Particle[p,0] = size_x/2
Particle[p,1]= size_y/2
Particle[p,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[p,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[p,4]= rand *1020# play with this setting until you get a nice bouncy effect
endif
next p
Download
currently, all particles are simply white. Based on the life parameter however, we can easily make the particles change color as they age.
There are of course many ways to map the age to a color. We will simply translate the age value to RGB colors.
Simply replace the following code:
color white
with the following code:
age=((Particle[p,4]/4) mod 255)
if age > 85 then
colblue = 255
colgreen = 255
colred = 255
color rgb(colred,colgreen,colblue)
else
if age >170 then
colblue = Particle[p,4] mod 255
colgreen = 255
colred = 255
color rgb(colred,colgreen,colblue)
else
colblue = 0
colgreen = Particle[p,4] mod 255
colred = 255
color rgb(colred,colgreen,colblue)
endif
endif
Download
The initial burst (the square full of particles that appears and bounces before the fountain really kicks in) is because we start the program by initializing all the particles in the system.
This of course also causes all particles to be alive at the chosen position at step 0.
To prevent this, we need to spawn particles all the time on the fly (and not just when one particle dies since then we'd have to wait for the initial particles to start dying first..)
For this, we replace the initialization of the Particle system so that all particles are DEAD (ie Particle [p,4]=0)
for p = 0 to Partnum - 1
Particle[p,4] = 0
next p
Then, during the main loop, the first thing we do is to continuously create a number of particles (here, 3 particles at every iteration). The number of particles here will depend on the total number and on the power of your PC.
for k = 1 to 3
spawni=int(rand * Partnum) # select a random particle
if Particle[spawni,4] = 0 then # if the particle is dead, create one
Particle[spawni,0] = size_x/2
Particle[spawni,1]= size_y/2
Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,4]= rand *1020 # play with this setting
end if
next k
In the next loop (where we update the particles) we first check if the particle in question is dead and if so skip the rest of the loop.
So ,
for p = 0 to Partnum-1 #write the particles to the buffer and update them
age=((Particle[p,4]/4) mod 255)
if age > 85 then
colblue = 255
colgreen = 255
colred = 255
color rgb(colred,colgreen,colblue)
else
...
endif
next p
would become
for p = 0 to Partnum-1 #write the particles to the buffer and update them
if Particle[p,4]>0 then
age=((Particle[p,4]/4) mod 255)
if age > 85 then
colblue = 255
colgreen = 255
colred = 255
color rgb(colred,colgreen,colblue)
else
...
endif
endif
endif
next p
Voila! That is all there is to it! Mind you, if your PC is very fast and if your particle's life duration is set too high, the piecemeal generation of new partivcles will be so fast that it will look as if the initial square is still there...
Fix this by giving you particles a shorter lifetime when creating them piecemeal but a longer one when respawning dead particles.
With these last changes, if we now run our program (particle07.kbs) we get from frame one, a nice particle fountain.
However, we did say we were going to control it with our mouse.
Well, this is quite simple! All we need to do is to initialize the x- and y-locations to the mouse positions!
Like this:
Particle[p,0]= size_x/2
Particle[spwani,0]= size_x/2
Particle[p,1]= size_y/2
Particle[spwani,1]= size_y/2
would then become:
Particle[p,0]= mousex
Particle[spawni,0]= mousex
Particle[p,1]= mousey
Particle[spawni,1]= mousey
Running the program now would immediately start the fountain at location 0,0 (seeing that the mouse coordinates have not yet been initialized).
We can fix this by simply checking if mousex is greater than 0 right at the start of the Loop construct:
Loop:
for k = 1 to 3
spawni=int(rand * Partnum) # select a random particle
if Particle[spawni,4] = 0 then # if the particle is dead, create one
Particle[spawni,0]= mousex
Particle[spawni,1]= mousey
Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,4]= rand *1020 # play with this setting
end if
next k
would then become:
Loop:
if mousex > 0 then
for k = 1 to 3
spawni=int(rand * Partnum) # select a random particle
if Particle[spawni,4] = 0 then # if the particle is dead, create one
Particle[spawni,0]= mousex
Particle[spawni,1]= mousey
Particle[spawni,2]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,3]= (rand-0.5)/5 # velocity from -0.1 to 0.1
Particle[spawni,4]= rand *1020 # play with this setting
end if
next k
endif
Voila! We now have Basic-256 program that gives us a nice particle fountain controlled by the mouse!!
DownloadIf you PC is fast enough, you can swap points for circles. For this, we just add a line in the main loop:
color rgb(colred,colgreen,colblue)
plot (Particle[p,0],Particle[p,1])
becomes:
color rgb(colred,colgreen,colblue)
# plot (Particle[p,0],Particle[p,1])
circle Particle[p,0],Particle[p,1],2
You can of course play around with the size of the circles.
Voila! all done! You can now start to experiment with increasing the screen dimension or the number of particles, changing the gravity parameter or the life duration, changing the speed at which particles are ejected (currently, we are using (rand-0.5)/0.5 for both x- and y-directions), etc. etc.
DownloadThe aim of this particle tutorial, is to have text decay in various ways.
At every interim step, it is the intention to have a working program so that you can see what the results are of the piecemeal changes. You can either cut and paste the code in this document to the Basic-256 code window (although indentation gets lost.) or use the hyperlinks to the example programs.
Basic-256 Boilerplate
For building up our particle system program, we will use the following scaffolding
Fastgraphics # write to video buffer.
size_x=800
size_y=800 # good practice to put every constant in a variable.
graphsize size_x,size_y # feel free to change the size of your canvas
color black
rect 0,0,size_x-1,size_y-1 # start out with a nice black screen.
color white
font "Tahoma",40,100
text 275,350,"Some Text"
refresh # dump the video buffer to screen
#Voila! This gives you a nice canvas to start with.
Running this program gives us "Some Text" on a nice black background. Not really exciting yet
Download Code